#include "Path.h"
#include <string.h>
#include <stdlib.h>

void path_init(Path* path)
{
    PathComponent* comp = (PathComponent*) malloc(sizeof(PathComponent));
    comp->component = NULL;
    comp->prev = comp;
    comp->next = comp;
    path->head = comp;
    path->tail = comp;
}

void path_destroy(Path* path)
{
    PathComponent* curr = path->head->next;
    while (curr != path->tail) {
        PathComponent* next = curr->next;
        free(curr->component);
        free(curr);
        curr = next;
    }
    free(path->head);

    path->head = NULL;
    path->tail = NULL;
}

/************************************************************/
/*                        构建路径                           */
/************************************************************/
static void path_append_component(Path* path, const char* component)
{
    PathComponent* newnode = (PathComponent*) malloc(sizeof(PathComponent));
    newnode->component = strdup(component);
    newnode->prev = path->tail->prev;
    newnode->next = path->tail;
    // 链接
    path->tail->prev->next = newnode;
    path->tail->prev = newnode;
}

static void path_prepend_component(Path* path, const char* component)
{
    PathComponent* newnode = (PathComponent*) malloc(sizeof(PathComponent));
    newnode->component = strdup(component);
    newnode->prev = path->head;
    newnode->next = path->head->next;
    // 链接
    path->head->next->prev = newnode;
    path->head->next = newnode;
}

static void path_pop_component(Path* path)
{
    if (path->tail->prev == path->head) {
        return;
    }
    PathComponent* comp = path->tail->prev;
    comp->prev->next = comp->next;
    comp->next->prev = comp->prev;
    free(comp->component);
    free(comp);
}

static void path_concatenate(Path* path, char* s)
{
    const char* component = strtok(s, "/");
    while (component) {
        if (strcmp(component, ".") == 0) {
            // do nothing
        } else if (strcmp(component, "..") == 0) {
            path_pop_component(path);
        } else {
            path_append_component(path, component);
        }
        component = strtok(NULL, "/");
    }
}

Path path_build(char* s)
{
    Path path;
    path_init(&path);
    path_concatenate(&path, s);
    return path;
}

char* path_str(const Path* path)
{
    char str[MAXPATH] = "/";
    PathComponent* curr = path->head->next;
    while (curr != path->tail) {
        // TODO: 待优化
        strcat(str, curr->component);
        strcat(str, "/");
        curr = curr->next;
    }
    return strdup(str);
}

Path path_cd_absolutely(char* s)
{
    return path_build(s);
}

Path path_cd_relatively(const Path* ref, char* s)
{
    char* str = path_str(ref);
    Path path = path_build(str);
    free(str);
    path_concatenate(&path, s);
    return path;
}
